﻿/*                       NOTICE
 * 
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-10-C-0001, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * Approved for Public Release: 11-2435
 * © 2011 The MITRE Corporation. All Rights Reserved. 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TUIO;

using System.Collections;
using System.Threading;
using System.Xml;
using System.Net;
using System.IO;
using RabbitMQ.Client.Impl;
using RabbitMQ.Client;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using MXSE.MultiTouch.Gestures;

namespace XNAGestureRecognition
{

    public class GestureRecognizer : TuioListener
    {

        private TuioClient tuioClient = new TuioClient();
        private List<string> contacts = new List<string>();
        // private HTTPServer server;

        private string configFile;
        private IConnection conn;
        private IModel channel;
        private IModel objectChannel;
        string serverAddress;// = "localhost";
        string exchange;// = "grip"; 
        string exchangeObject;// = "grip-fiducial";
        string queue;// = "grip-gestures";
        string objectQ;// = "grip-objects";
        string routingKey;// = "";
        
        TUIOContactManager contactManager;
        TUIOObjectManager objectManager;
        private int msgNum=0;
        public GestureRecognizer(Game game, string configFile)
        {
            this.configFile = configFile;
            if(configFile != null)
                parseConfigSettings();

            TuioClient tuioClient = new TuioClient();


            Console.WriteLine("Connecting to RabbitMQ...");

            ConnectionFactory factory = new ConnectionFactory();

            factory.HostName = serverAddress;
            factory.Port = AmqpTcpEndpoint.UseDefaultPort;
            conn = factory.CreateConnection();


            channel = conn.CreateModel();
            Console.WriteLine("Starting Topic...and Q");
            channel.ExchangeDeclare(exchange, ExchangeType.Fanout);
            channel.QueueDeclare(queue, true, false, true, null);
            channel.QueueBind(queue, exchange, routingKey, null);
            

            objectChannel = conn.CreateModel();
            Console.WriteLine("Starting Topic...and Q for Objects");
            objectChannel.ExchangeDeclare(exchangeObject, ExchangeType.Fanout);
            objectChannel.QueueDeclare(objectQ, true, false, true, null);
            objectChannel.QueueBind(objectQ, exchangeObject, routingKey, null);
            
            contactManager = new TUIOContactManager(game);
            objectManager = new TUIOObjectManager(game);

            tuioClient.addTuioListener(this);
            tuioClient.connect();

            initializeGestureInput();


        }

        // Grabs the config parameters out of the given config file.
        protected void parseConfigSettings()
        {
            using (StreamReader reader = new StreamReader(configFile))
            {
                Dictionary<string, string> settingLookup = new Dictionary<string, string>();
                string line = reader.ReadLine();
                while (line != null)
                {
                    string[] elements = line.Split(':');
                    if (elements.Length > 1)
                        settingLookup.Add(elements[0], elements[1].TrimStart(' '));
                    line = reader.ReadLine();
                }

                serverAddress = settingLookup["serverAddress"];
                exchange = settingLookup["exchange"];
                exchangeObject = settingLookup["exchangeObject"];
                queue = settingLookup["queue"];
                objectQ = settingLookup["objectQ"];
                routingKey = settingLookup["routingKey"];

                reader.Close();
            }
        }

        protected void initializeGestureInput()
        {
            /*
            //Default constructors are set for the gestures, but they need actions.
           
            //Use typeof() to set which Gesture will perform this action.
            contactManager.AddAction(typeof(DragGesture), (gesture) =>
            {
                //Cast the given gesture to the correct type.
                DragGesture g = (DragGesture)gesture;
                if (g.Parent == null)
                {
                    if (contactManager.getDistance(g.lastPosition, g.currentPosition) > 0)
                    {
                        //Write a message to the Console as an example action.
                        Console.WriteLine("DragGesture active at " + g.currentPosition);

                        String body = createGestureXml(g.Id, "Dragging", g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y);
                        //Console.WriteLine("Sending Move Gesture...");
                        IBasicProperties basicProperties = channel.CreateBasicProperties();
                        basicProperties.Expiration = "100";

                        TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
                        long unixTime = (long)ts.TotalSeconds;
                        basicProperties.Timestamp = new AmqpTimestamp(unixTime);
                        basicProperties.MessageId = msgNum.ToString();

                        channel.BasicPublish(exchange,
                                          routingKey,
                                          basicProperties,
                                          Encoding.UTF8.GetBytes(body));
                    }
                }
            });


            //Add a camera panning action to the SlideGesture
            contactManager.AddAction(typeof(SlideGesture), (gesture) =>
            {
                SlideGesture g = (SlideGesture)gesture;
                //Check for pure slides.
                if (g.Parent == null)
                {
                    if (contactManager.getDistance(g.lastPosition, g.currentPosition) > 0)
                    {
                        String body = createGestureXml(g.Id, "Move", g.startPosition.X, g.startPosition.Y, g.lastPosition.X, g.lastPosition.Y, g.currentPosition.X, g.currentPosition.Y);
                        //Console.WriteLine("Sending Move Gesture...");
                        IBasicProperties basicProperties = channel.CreateBasicProperties();
                        basicProperties.Expiration = "100";

                        TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
                        long unixTime = (long)ts.TotalSeconds;
                        basicProperties.Timestamp = new AmqpTimestamp(unixTime);
                        basicProperties.MessageId = msgNum.ToString();
                        
                        channel.BasicPublish(exchange,
                                          routingKey,
                                          basicProperties,
                                          Encoding.UTF8.GetBytes(body));
                        msgNum++;
                        
                    }
                    
                }
            });

            //Zoom towards center of gesture
            contactManager.AddAction(typeof(ZoomGesture), (gesture) =>
            {
                ZoomGesture g = (ZoomGesture)gesture;

                if (Math.Abs(lastmagnitude - g.magnitude) > 0.001)
                {
                    lastmagnitude = g.magnitude;
                    DragGesture dragOne = (DragGesture)g.Basics[0], dragTwo = (DragGesture)g.Basics[1];
                    double delta = contactManager.getDistance(dragOne.currentPosition, dragTwo.currentPosition) - contactManager.getDistance(dragOne.lastPosition, dragTwo.lastPosition);

                    //Zoom in on position instead of center:
                    float movementPercentage = (float)(delta / contactManager.getDistance(dragOne.lastPosition, dragTwo.lastPosition));
                    //String type = g.Direction.Equals("In") ? "Pulling":"Pinching";
                    String type = "Pinching";
                    //String body = createGestureXml(g.Basics[0].Id + g.Basics[1].Id, type, slideOne.lastPosition.X, slideOne.lastPosition.Y, slideOne.lastPosition.X, slideOne.lastPosition.Y, g.centerPosition().X, g.centerPosition().Y);
                    String body = createGestureXml(g.Basics[0].Id + g.Basics[1].Id, type, 0, 0, 0, 0, (float)g.magnitude, g.direction);

                    Console.WriteLine("Sending Zoom Gesture...");
                    IBasicProperties basicProperties = channel.CreateBasicProperties();
                    basicProperties.Expiration = "100";

                    TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
                    long unixTime = (long)ts.TotalSeconds;
                    basicProperties.Timestamp = new AmqpTimestamp(unixTime);
                    channel.BasicPublish(exchange,
                                      routingKey,
                                      basicProperties,
                                      Encoding.UTF8.GetBytes(body));
                }
            });

            //Rotate Camera
            contactManager.AddAction(typeof(RotationGesture), (gesture) =>
            {
                RotationGesture g = (RotationGesture)gesture;
                SlideGesture slide = (SlideGesture)g.Basics[1];
                TouchGesture touch = (TouchGesture)g.Basics[0];
                if (slide.lastPosition == slide.currentPosition)
                    return;

                
                /*Vector2 last = Vector2.Normalize(slide.lastPosition - touch.startPosition);
                Vector2 cur = Vector2.Normalize(slide.currentPosition - touch.startPosition);
                double lastAngle = Vector2.Dot(last, Vector2.UnitX);
                double delta = 0;
                double currentAngle = Vector2.Dot(cur, Vector2.UnitX); ;
                if (Math.Abs(lastAngle) < .9 && Math.Abs(currentAngle) < .9)
                {
                    lastAngle = Math.Acos(lastAngle);
                    currentAngle = Math.Acos(currentAngle);
                    delta = currentAngle - lastAngle;
                    if (touch.startPosition.Y < slide.currentPosition.Y)
                        delta = -delta;
                }
                {
                    lastAngle = Vector2.Dot(last, Vector2.UnitY);
                    currentAngle = Vector2.Dot(cur, Vector2.UnitY);
                    lastAngle = Math.Acos(lastAngle);
                    currentAngle = Math.Acos(currentAngle);
                    delta = currentAngle - lastAngle;
                    if (touch.startPosition.X > slide.currentPosition.X)
                        delta = -delta;
                }
                camera.targetAngles.Z -= (float)delta;
                 
            });


            //Test of SecondTapGesture
            contactManager.AddAction(typeof(SecondTapGesture), (gesture) =>
            {
                SecondTapGesture g = (SecondTapGesture)gesture;
                String body = createGestureXml(g.Basics[0].Id, "DoubleTap", g.Basics[0].currentPosition.X, g.Basics[0].currentPosition.Y, g.Basics[0].currentPosition.X, g.Basics[0].currentPosition.Y, g.Basics[0].currentPosition.X, g.Basics[0].currentPosition.Y);


                Console.WriteLine("Sending Double Tap Gesture...");
                IBasicProperties basicProperties = channel.CreateBasicProperties();
                basicProperties.Expiration = "100";

                TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
                long unixTime = (long)ts.TotalSeconds;
                basicProperties.Timestamp = new AmqpTimestamp(unixTime);
                channel.BasicPublish(exchange,
                                  routingKey,
                                  basicProperties,
                                  Encoding.UTF8.GetBytes(body));
            });



            //Add picking support.
            contactManager.AddAction(typeof(TapGesture), (gesture) =>
            {
                
                    TapGesture g = (TapGesture)gesture;
                    String body = createGestureXml(g.Id, "Tap", g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y);


                    Console.WriteLine("Sending Tap Gesture...");
                    IBasicProperties basicProperties = channel.CreateBasicProperties();
                   // basicProperties.Expiration = "100";

                    TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
                    long unixTime = (long)ts.TotalSeconds;
                    basicProperties.Timestamp = new AmqpTimestamp(unixTime);
                    basicProperties.MessageId = msgNum.ToString();
                    channel.BasicPublish(exchange,
                                      routingKey,
                                      basicProperties,
                                      Encoding.UTF8.GetBytes(body));
                    msgNum++;
                   

                
                   
            });

            //Grab everything in the box for a BoxingGesture
            contactManager.AddAction(typeof(BoxingGesture), (gesture) =>
            {
                BoxingGesture g = (BoxingGesture)gesture;

                
            });

            //Open menu with HoldSlideGesture
            contactManager.AddAction(typeof(HoldSlideGesture), (gesture) =>
            {
                HoldSlideGesture g = (HoldSlideGesture)gesture;

                Vector3 v = g.Basics[1].currentPosition - g.Basics[0].startPosition;
                v.Normalize();
                float dot = Vector3.Dot(v, Vector3.UnitX);
                double rot = Math.Acos(dot);
                if (g.Basics[1].currentPosition.Y < g.Basics[0].startPosition.Y)
                    rot = -rot;
                int a = (int)(rot / (Math.PI / 4));
                if (rot - a * (Math.PI / 4) > Math.PI / 8)
                    a++;
               
            });*/
        }

        private long getUnixTime()
        {
            return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
        }

        /*
        #region Actions

        #region DragGesture Actions
        private void addDragGestureActions()
        {
            DragGesture.startAction = (gesture =>
            {
                DragGesture g = (DragGesture)gesture;
                publishMessage("Starting drag " + g.Id + " at " + g.currentPosition, "DragStart", g.Id, g.startPosition.X, g.startPosition.Y, g.lastPosition.X, g.lastPosition.Y, g.currentPosition.X, g.currentPosition.Y);
            });

            DragGesture.updateAction = (gesture =>
            {
                DragGesture g = (DragGesture)gesture;
                });

            DragGesture.endAction = (gesture =>
            {
                DragGesture g = (DragGesture)gesture;
                publishMessage("Drag " + g.Id + " ended.", "DragComplete", g.Id, g.startPosition.X, g.startPosition.Y, g.lastPosition.X, g.lastPosition.Y, g.currentPosition.X, g.currentPosition.Y);
            });
        }
        #endregion

        #endregion
        */


        #region TuioListener Members

        public void addTuioObject(TuioObject tuioObject)
        {
            objectManager.objects.Add(tuioObject.getFiducialID(), tuioObject);
            String body = createObjectXml(tuioObject.getFiducialID(), "AddObject", tuioObject.getX(), tuioObject.getY());

            IBasicProperties basicProperties = objectChannel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            objectChannel.BasicPublish(exchangeObject,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
        }

        public void updateTuioObject(TuioObject tuioObject)
        {
            TuioObject test = null;
            objectManager.objects.TryGetValue(tuioObject.getFiducialID(),out test);
            if (test !=null){
            String body = createObjectXml(tuioObject.getFiducialID(), "UpdateObject", tuioObject.getX(), tuioObject.getY());

            IBasicProperties basicProperties = objectChannel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            objectChannel.BasicPublish(exchangeObject,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
            }
        }

        public void removeTuioObject(TuioObject tuioObject)
        {
            objectManager.objects.Remove(tuioObject.getFiducialID());
            String body = createObjectXml(tuioObject.getFiducialID(), "RemoveObject", tuioObject.getX(), tuioObject.getY());

            IBasicProperties basicProperties = objectChannel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            objectChannel.BasicPublish(exchangeObject,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
        }

        public void addTuioCursor(TuioCursor tuioCursor)
        {
            contactManager.ContactAdded(tuioCursor);
        }

        public void updateTuioCursor(TuioCursor tuioCursor)
        {
            contactManager.ContactChanged(tuioCursor);
        }

        public void removeTuioCursor(TuioCursor tuioCursor)
        {
            contactManager.ContactRemoved(tuioCursor);
        }

        public void refresh(long timestamp)
        {
            // throw new NotImplementedException();
        }

        #endregion










        private int messageId = 0;
        /*public void OnGestureEvent(object gr, GestureEventArgs args)
        {






            BasicMultiFingerEventArgs cArgs = (BasicMultiFingerEventArgs)args;

            // Console.WriteLine(cArgs.EventId + ":" + cArgs.X + ":" + cArgs.Y);
            //Just for debugging to make sure this gets the message

            //contacts.Add(cArgs.EventId + ":" + cArgs.X + ":" + cArgs.Y);

            Console.WriteLine("Starting Coords:" + cArgs.StartX + "," + cArgs.StartY + " Last Coords: " + cArgs.LastX + "," + cArgs.LastY + " Current Coords: " + cArgs.X + ":" + cArgs.Y);
            //make the xml snippet and post to subscribers
            String body = createGestureXml(args, cArgs.StartX, cArgs.StartY, cArgs.LastX, cArgs.LastY, cArgs.X, cArgs.Y);

            Console.WriteLine("Sending Gesture...");
            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.MessageId = messageId.ToString();
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            channel.BasicPublish(exchange,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));

            messageId++;


        }
         */

        /* public void OnPinchEvent(object gr, GestureEventArgs args)
         {

             PinchEventArgs cArgs = (PinchEventArgs)args;

             // Console.WriteLine(cArgs.EventId + ":" + cArgs.X + ":" + cArgs.Y);
             //Just for debugging to make sure this gets the message

             //contacts.Add(cArgs.EventId + ":" + cArgs.X + ":" + cArgs.Y);

             Console.WriteLine("Starting Coords:" + cArgs.X + "," + cArgs.Y + " Last Coords: " + cArgs.X + "," + cArgs.Y + " Current Coords: " + cArgs.X + ":" + cArgs.Y);
             //make the xml snippet and post to subscribers
             String body = createGestureXml(args, cArgs.X, cArgs.Y, cArgs.X, cArgs.Y, cArgs.X, cArgs.Y);

             channel.BasicPublish(exchange,
                               routingKey,
                               null,
                               Encoding.UTF8.GetBytes(body));


             /* if (server.Subscribers[cArgs.EventId].Count != 0)
              {
                  foreach (string host in server.Subscribers[cArgs.EventId])
                  {
                      PostXml(host, body);
                  }
              }
             
         }*/


        /*public String PostXml(string url, string xml)
        {
            byte[] bytes = Encoding.ASCII.GetBytes(xml);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentLength = bytes.Length;
            request.ContentType = "text/plain";
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(bytes, 0, bytes.Length);
            }
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        string message = String.Format(
                        "POST failed. Received HTTP {0}",
                        response.StatusCode);
                        throw new ApplicationException(message);
                    }
                }
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }
        }*/

        public void publishMessage(string message, string gestureType, long id, float startX, float startY, float lastX, float lastY, float currentX, float currentY)
        {
            Console.WriteLine(message);

            String body = createGestureXml(id, gestureType, startX, startY, lastX, lastY, currentX, currentY);

            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.Expiration = "100";
            basicProperties.Timestamp = new AmqpTimestamp(getUnixTime());
            basicProperties.MessageId = msgNum.ToString();

            channel.BasicPublish(exchange, routingKey, basicProperties, Encoding.UTF8.GetBytes(body));
        }

        private string createGestureXml(long id,String type, float start_x, float start_y, float last_x, float last_y, float cur_x, float cur_y)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement root = doc.CreateElement("gestures");
            XmlElement gesture = doc.CreateElement("gesture");

            gesture.SetAttribute("id", id.ToString());
            gesture.SetAttribute("type", type);
            gesture.SetAttribute("time", DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
            root.AppendChild(gesture);
            XmlElement coordinates = doc.CreateElement("coordinates");
            /*
            XmlElement startcoordinate = doc.CreateElement("coordinate");
            startcoordinate.SetAttribute("x", cur_x.ToString());
            startcoordinate.SetAttribute("y", cur_y.ToString());
            startcoordinate.SetAttribute("type", "CONTACT");

            XmlElement lastcoordinate = doc.CreateElement("coordinate");
            lastcoordinate.SetAttribute("x", cur_x.ToString());
            lastcoordinate.SetAttribute("y", cur_y.ToString());
            lastcoordinate.SetAttribute("type", "CONTACT");
            */
            XmlElement currentcoordinate = doc.CreateElement("coordinate");
            currentcoordinate.SetAttribute("x", cur_x.ToString());
            currentcoordinate.SetAttribute("y", cur_y.ToString());
            currentcoordinate.SetAttribute("type", "CONTACT");
            gesture.AppendChild(coordinates);
            //coordinates.AppendChild(startcoordinate);
            //coordinates.AppendChild(lastcoordinate);
            coordinates.AppendChild(currentcoordinate);

            doc.AppendChild(root);

            return doc.InnerXml;

        }

        public string createObjectXml(long id, String type, float cur_x, float cur_y)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement root = doc.CreateElement("objects");
            XmlElement gesture = doc.CreateElement("object");

            gesture.SetAttribute("id", id.ToString());
            gesture.SetAttribute("type", type);
            gesture.SetAttribute("time", DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
            root.AppendChild(gesture);
            XmlElement coordinates = doc.CreateElement("coordinates");
            XmlElement coordinate = doc.CreateElement("coordinate");
            coordinate.SetAttribute("x", cur_x.ToString());
            coordinate.SetAttribute("y", cur_y.ToString());
            coordinate.SetAttribute("type", "CONTACT");
            gesture.AppendChild(coordinates);
            coordinates.AppendChild(coordinate);

            doc.AppendChild(root);

            return doc.InnerXml;

        }
        /*
        public void sendDragGestureAddedMessage(DragGesture g)
        {
            //Write a message to the Console as an example action.
            Console.WriteLine("DragGesture started at " + g.currentPosition);

            String body = createGestureXml(g.Id, "DragStart", g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y);
            //Console.WriteLine("Sending Move Gesture...");
            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            basicProperties.MessageId = msgNum.ToString();

            channel.BasicPublish(exchange,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
        }

        public void sendDragGestureEndedMessage(DragGesture g)
        {
            Console.WriteLine("DragGesture ended.");

            String body = createGestureXml(g.Id, "DragComplete", g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y, g.currentPosition.X, g.currentPosition.Y);
            //Console.WriteLine("Sending Move Gesture...");
            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            basicProperties.MessageId = msgNum.ToString();

            channel.BasicPublish(exchange,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
        }

        public void sendZoomGestureAddedMessage(ZoomGesture g)
        {
            Vector3 centroid = new Vector3();
            Vector3 pos1 = g.Basics[0].currentPosition, pos2 = g.Basics[1].currentPosition;
            centroid.X = (pos1.X + pos2.X) / 2;
            centroid.Y = (pos1.Y + pos2.Y) / 2;
            centroid.Z = (pos1.Z + pos2.Z) / 2;
            Console.WriteLine("ZoomGesture started at " + centroid);

            String body = createGestureXml(g.Basics[0].Id + g.Basics[1].Id, "PinchStart", centroid.X, centroid.Y, centroid.X, centroid.Y, centroid.X, centroid.Y);
            //Console.WriteLine("Sending Move Gesture...");
            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            basicProperties.MessageId = msgNum.ToString();

            channel.BasicPublish(exchange,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
        }

        public void sendZoomGestureEndedMessage(ZoomGesture g)
        {
            Console.WriteLine("ZoomGesture ended.");

            String body = createGestureXml(g.Basics[0].Id + g.Basics[1].Id, "PinchComplete", 0, 0, 0, 0, 0, 0);
            //Console.WriteLine("Sending Move Gesture...");
            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.Expiration = "100";

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            long unixTime = (long)ts.TotalSeconds;
            basicProperties.Timestamp = new AmqpTimestamp(unixTime);
            basicProperties.MessageId = msgNum.ToString();

            channel.BasicPublish(exchange,
                              routingKey,
                              basicProperties,
                              Encoding.UTF8.GetBytes(body));
        }
        */
         
    }
    
}
